/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package SintaticoPacote;

import SintaticoPacote.TratamentoErro.ErroTabela;
import SintaticoPacote.TratamentoErro.TabelaErros;
import compilador_full.TabelaSimbolos;

/**
 *
 * @author Jomas
 */
public class declaracaoStructs {

    private TabelaSimbolos tabelaSimbolos;

    public declaracaoStructs(TabelaSimbolos tabelaSimbolos)
    {
        this.tabelaSimbolos = tabelaSimbolos;
    }
    public boolean declaraStructs(){

        if(tabelaSimbolos.getLookahead().equals("typedef"))
        {

            tabelaSimbolos.reconhecer(tabelaSimbolos.getLookahead());
            tabelaSimbolos.superBuscaEscopo();

            if(tabelaSimbolos.getLookahead().equals("struct")) {
                tabelaSimbolos.reconhecer("struct");
            } else
            {
                ErroTabela erro = new ErroTabela(tabelaSimbolos.getLinha(),"Erro na linha "+ tabelaSimbolos.getLinha() + "Faltou a palavra struct");
                TabelaErros.getInstance().getTabelaErros().add(erro);// Tabela de Erros ja contem o erro. Isso que será impresso na tela.
                return false;
            }
            if(tabelaSimbolos.getLookahead().equals("{"))
                tabelaSimbolos.reconhecer("{");
            else
            {
                ErroTabela erro = new ErroTabela(tabelaSimbolos.getLinha(),"Erro na linha "+ tabelaSimbolos.getLinha() + "Deveria vir um {");
                TabelaErros.getInstance().getTabelaErros().add(erro);// Tabela de Erros ja contem o erro. Isso que será impresso na tela.
                return false;
            }
            boolean verifica = true;
            while(verifica == true)
            {
              verifica =  declaraVariaveisStruct();
              if(verifica == false)
                  return false;//Erro em declaracao variavel struct
              if(tabelaSimbolos.getLookahead().equals("}"))
                  verifica = false;
            }
            if(tabelaSimbolos.getLookahead().equals("}"))
                tabelaSimbolos.reconhecer("}");
            else
            {
                ErroTabela erro = new ErroTabela(tabelaSimbolos.getLinha(),"Erro na linha "+ tabelaSimbolos.getLinha() + "Deveria fechar }");
                TabelaErros.getInstance().getTabelaErros().add(erro);// Tabela de Erros ja contem o erro. Isso que será impresso na tela.
                return false;
            }

            if(tabelaSimbolos.getTipo().equals("identificador")) {
                // insere categoria
                tabelaSimbolos.insertCategoria("struct");
                
                // constroi o tipo
                tabelaSimbolos.salvaTipo("struct");

                // insere tipo
                tabelaSimbolos.insertTipoVariavel();
                // insere o escopo
                tabelaSimbolos.insertEscopo2();

                tabelaSimbolos.reconhecer(tabelaSimbolos.getLookahead());
            } else
            {
                ErroTabela erro = new ErroTabela(tabelaSimbolos.getLinha(),"Erro na linha "+ tabelaSimbolos.getLinha() + "Erro de Reconhecimento");
                TabelaErros.getInstance().getTabelaErros().add(erro);// Tabela de Erros ja contem o erro. Isso que será impresso na tela.
                return false;
            }

            if(tabelaSimbolos.getLookahead().equals(";"))
            {
                tabelaSimbolos.reconhecer(tabelaSimbolos.getLookahead());
                return true;
            }
            else
            {
                ErroTabela erro = new ErroTabela(tabelaSimbolos.getLinha(),"Erro na linha "+ tabelaSimbolos.getLinha() + "Deveria vir o ;");
                TabelaErros.getInstance().getTabelaErros().add(erro);// Tabela de Erros ja contem o erro. Isso que será impresso na tela.
                return false;
            }

        }
        else if(tabelaSimbolos.getLookahead().equals("struct"))
        {
            tabelaSimbolos.reconhecer("struct");
            if(tabelaSimbolos.getLookahead().equals("{"))
                tabelaSimbolos.reconhecer("{");
            else
            {
                ErroTabela erro = new ErroTabela(tabelaSimbolos.getLinha(),"Erro na linha "+ tabelaSimbolos.getLinha() + "Faltou o {");
                TabelaErros.getInstance().getTabelaErros().add(erro);// Tabela de Erros ja contem o erro. Isso que será impresso na tela.
                return false;
            }
            boolean verifica = true;
            while(verifica == true)
            {
              verifica =  declaraVariaveisStruct();
              if(verifica == false)
                  return false;//Erro em declaracao variavel struct
              if(tabelaSimbolos.getLookahead().equals("}"))
                  verifica = false;
            }
            if(tabelaSimbolos.getLookahead().equals("}"))
                tabelaSimbolos.reconhecer("}");
            else
            {
                ErroTabela erro = new ErroTabela(tabelaSimbolos.getLinha(),"Erro na linha "+ tabelaSimbolos.getLinha() + "Faltou o }");
                TabelaErros.getInstance().getTabelaErros().add(erro);// Tabela de Erros ja contem o erro. Isso que será impresso na tela.
                return false;
            }
            if(tabelaSimbolos.getTipo().equals("identificador")){

                // insere categoria
                tabelaSimbolos.insertCategoria("struct");

                // constroi o tipo
                tabelaSimbolos.salvaTipo("struct");

                // insere tipo
                tabelaSimbolos.insertTipoVariavel();
                // insere o escopo
                tabelaSimbolos.insertEscopo2();

                tabelaSimbolos.reconhecer(tabelaSimbolos.getLookahead());
            }
            else
            {
                ErroTabela erro = new ErroTabela(tabelaSimbolos.getLinha(),"Erro na linha "+ tabelaSimbolos.getLinha() + "Deveria ser um identificador");
                TabelaErros.getInstance().getTabelaErros().add(erro);// Tabela de Erros ja contem o erro. Isso que será impresso na tela.
                return false;
            }
            if(tabelaSimbolos.getLookahead().equals(";"))
            {
                tabelaSimbolos.reconhecer(tabelaSimbolos.getLookahead());
                return true;
            }
            else
            {
                ErroTabela erro = new ErroTabela(tabelaSimbolos.getLinha(),"Erro na linha "+ tabelaSimbolos.getLinha() + "Faltou o ;");
                TabelaErros.getInstance().getTabelaErros().add(erro);// Tabela de Erros ja contem o erro. Isso que será impresso na tela.
                return false;
            }
        }
        else
        {
            ErroTabela erro = new ErroTabela(tabelaSimbolos.getLinha(),"Erro na linha "+ tabelaSimbolos.getLinha() +  "Expressao não reconhecida");
            TabelaErros.getInstance().getTabelaErros().add(erro);// Tabela de Erros ja contem o erro. Isso que será impresso na tela.
            return false;
        }
    }

    public boolean declaraVariaveisStruct()
    {
        if(Tipos.apenasCompara(tabelaSimbolos))
        {
            // salva o tipo
            tabelaSimbolos.salvaTipo(tabelaSimbolos.getLookahead());


            tabelaSimbolos.reconhecer(tabelaSimbolos.getLookahead());

            // insere o escopo
            tabelaSimbolos.insertEscopo();
            // insere tipo
            tabelaSimbolos.insertTipoVariavel();
            // insere categoria
            tabelaSimbolos.insertCategoria("variavel");
            
            
            if(tabelaSimbolos.getTipo().equals("identificador")){
               // System.out.println("escopo 2 eh " + tabelaSimbolos.superBuscaEscopo());
                tabelaSimbolos.put2Escopo2(tabelaSimbolos.superBuscaEscopo());
                tabelaSimbolos.reconhecer(tabelaSimbolos.getLookahead());

            }
                
            else
            {
                ErroTabela erro = new ErroTabela(tabelaSimbolos.getLinha(),"Erro na linha "+ tabelaSimbolos.getLinha() + "Deveria vir um identificador");
                TabelaErros.getInstance().getTabelaErros().add(erro);// Tabela de Erros ja contem o erro. Isso que será impresso na tela.
                return false;
            }

            if(casoVetor()== false)
                return false;//Erro em caso vetor
            while(tabelaSimbolos.getLookahead().equals(","))
            {
                tabelaSimbolos.reconhecer(",");


                // insere o escopo
            tabelaSimbolos.insertEscopo();
            // insere tipo
            tabelaSimbolos.insertTipoVariavel();
            // insere categoria
            tabelaSimbolos.insertCategoria("variavel");

                if(tabelaSimbolos.getTipo().equals("identificador")){
                    tabelaSimbolos.put2Escopo2(tabelaSimbolos.superBuscaEscopo());
                    tabelaSimbolos.reconhecer(tabelaSimbolos.getLookahead());
                }
                if(casoVetor()== false)
                    return false;//Erro em caso vetor
                if(tabelaSimbolos.getLookahead().equals(";"))
                {
                    tabelaSimbolos.reconhecer(tabelaSimbolos.getLookahead());
                    return true;
                }

            }
            if(tabelaSimbolos.getLookahead().equals(";"))
            {
                tabelaSimbolos.reconhecer(tabelaSimbolos.getLookahead());
                return true;
            }
            return true;
        }
        else
        {
            ErroTabela erro = new ErroTabela(tabelaSimbolos.getLinha(),"Erro na linha "+ tabelaSimbolos.getLinha() + " Deveria vir tipo");
            TabelaErros.getInstance().getTabelaErros().add(erro);// Tabela de Erros ja contem o erro. Isso que será impresso na tela.
            return false;
        }
    }
    private boolean casoVetor()
    {
        while(tabelaSimbolos.getLookahead().equals("["))
        {
            tabelaSimbolos.reconhecer("[");
            if(tabelaSimbolos.getTipo().equals("numero"))
                tabelaSimbolos.reconhecer(tabelaSimbolos.getLookahead());
            else if(tabelaSimbolos.getTipo().equals("identificador"))
                tabelaSimbolos.reconhecer(tabelaSimbolos.getLookahead());
            else
            {
                ErroTabela erro = new ErroTabela(tabelaSimbolos.getLinha(),"Erro na linha "+ tabelaSimbolos.getLinha() + "Não pôde reconhecer");
                TabelaErros.getInstance().getTabelaErros().add(erro);// Tabela de Erros ja contem o erro. Isso que será impresso na tela.
                return false;
            }
            if(tabelaSimbolos.getLookahead().equals("]"))
                tabelaSimbolos.reconhecer("]");
            else
            {
                ErroTabela erro = new ErroTabela(tabelaSimbolos.getLinha(),"Erro na linha "+ tabelaSimbolos.getLinha() + "Faltou o ]");
                TabelaErros.getInstance().getTabelaErros().add(erro);// Tabela de Erros ja contem o erro. Isso que será impresso na tela.
                return false;
            }
        }
        return true;
    }
}
